<script setup lang="ts" name="MySku">
import type {
  GoodsDetail,
  Value,
  Spec,
  Sku,
} from '@/components/XtxUI/Sku/goods';
import bwPowerSet from '@/vendor/power-set';
const props = defineProps<{ goods: GoodsDetail }>();
export interface SkuEmit {
  skuId: string;
  price: string;
  oldPrice: string;
  inventory: number;
}
const emits = defineEmits<{
  (e: 'change', val: SkuEmit): void;
}>();
// 处理可走路径字典对象
type PathMap = { [key: string]: string[] };
type Skus = Sku[];
const spliter = '★';
// 获取选中的规格的值
// 原则：得到的结果要保证顺序 ["选中规格", undefined, undefined]
// 🚨 由于书写顺序问题，可以用 function 定义函数提升
function getSelectedSpec(specs: Specs) {
  // 注意类型定义
  const arr: string[] = [];
  specs.forEach((spec, index) => {
    // 根据spec中values中找是否有，selected为true的，把selected为true的那个按钮存储起来
    const btnObj = spec.values.find((item) => item.selected);
    // 如果为选中，就把 name 添加到数组中
    arr[index] = btnObj ? btnObj.name : '';
  });
  return arr;
}
// 点击选中状态，之前选中则取反，之前没选中，排他。
function changeSku(btnObj: Value, spec: Spec) {
  if (btnObj.disabled) return;
  if (btnObj.selected) {
    btnObj.selected = false;
  } else {
    spec.values.forEach((item) => {
      item.selected = false;
    });
    btnObj.selected = true;
  }
  updateDisabledStatus(props.goods.specs, pathMap);
  const selectedArr = getSelectedSpec(props.goods.specs);
  console.log(selectedArr, 'selectarr');
  if (selectedArr.length === props.goods.specs.length) {
    // 根据选中组合去字典查找。
    const getSkupath = pathMap[selectedArr.join(spliter)];
    if (!getSkupath) {
      return;
    }
    const skuId = getSkupath[0];
    const sku = props.goods.skus.find((sku) => sku.id == skuId);
    if (sku) {
      // 传递给父组件
      emits('change', {
        skuId: sku.id,
        price: sku.price,
        oldPrice: sku.oldPrice,
        inventory: sku.inventory,
      });
    }
  }
}

// 根据skus数据得到路径字典对象
const getPathMap = (skus: Skus) => {
  // 0. 初始化可走路径字典对象为空对象
  const pathMap = {} as PathMap;
  // 1. 遍历 skus 集合
  skus.forEach((sku) => {
    // 2. 过滤出有库存有效的sku
    if (sku.inventory) {
      // 3. 得到sku属性值数组 ,有效的sku
      const specs = sku.specs.map((spec) => spec.valueName);
      // 4. 得到sku属性值数组的子集
      const powerSet = bwPowerSet(specs);
      // 有效的子集。
      // console.log(powerSet, 'powerset');

      // 5. 设置给路径字典对象
      powerSet.forEach((set) => {
        // 6. 处理成字符串方便查找
        const key = set.join(spliter);
        // console.log(key, 'key');

        // 7. 如果还没有数组，创建一个空数组
        if (!pathMap[key]) {
          pathMap[key] = [];
        }
        // 8. 已经有key往数组追加 skuid
        pathMap[key].push(sku.id);
      });
    }
  });
  return pathMap;
};

// 🚨 更新按钮的禁用状态
// 🚨 更新禁用状态核心：获取当前用户选中的规格，再模拟用户下一次的规格选择，去字典中查询，查询不到设置为禁用状态
type Specs = Spec[];
// 更新按钮的禁用状态
const updateDisabledStatus = (specs: Specs, pathMap: PathMap) => {
  // 遍历每一种规格
  specs.forEach((spec, i) => {
    // 先拿到当前选择的项目
    const selectedValues = getSelectedSpec(specs);
    console.log('selected', selectedValues);
    // console.log(spec, 'spec');

    // 遍历每一个按钮
    spec.values.forEach((btnObj) => {
      console.log(btnObj.selected, 'obj');

      // 如果按钮未被选择
      if (!btnObj.selected) {
        // 🚨模拟用户选择
        selectedValues[i] = btnObj.name;
        // 去掉空值之后组合成查找字典的 key
        const key = selectedValues.filter((v) => v).join(spliter);
        // 判断组合后的情况，在字典中是否能找到
        if (pathMap[key]) {
          btnObj.disabled = false;
        } else {
          btnObj.disabled = true;
        }
      }
    });
  });
};

// // 获取可走路径字典对象
const pathMap = getPathMap(props.goods.skus);
console.log(`组合字典结果`, pathMap);

// ⌛ 组件初始化的时候更新禁用状态
updateDisabledStatus(props.goods.specs, pathMap);
</script>

<template>
  <div class="goods-sku">
    <dl v-for="sku in goods.specs" :key="sku.id">
      <dt>{{ sku.name }}</dt>
      <dd>
        <div v-for="(skuInfo, index) in sku.values" :key="index">
          <img
            v-if="skuInfo.picture"
            :class="{ selected: skuInfo.selected, disabled: skuInfo.disabled }"
            :src="skuInfo.picture"
            alt=""
            @click="changeSku(skuInfo, sku)"
          />
          <span
            v-else
            :class="{ selected: skuInfo.selected, disabled: skuInfo.disabled }"
            @click="changeSku(skuInfo, sku)"
          >
            {{ skuInfo.name }}
          </span>
        </div>
      </dd>
    </dl>
  </div>
</template>

<style scoped lang="less">
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  cursor: pointer;
  &.selected {
    border-color: @xtxColor;
  }
  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}
.goods-sku {
  padding-left: 10px;
  padding-top: 20px;
  dl {
    display: flex;
    flex-wrap: wrap;
    padding-bottom: 20px;
    align-items: center;
    dt {
      width: 50px;
      color: #999;
    }
    dd {
      flex: 1;
      display: flex;
      flex-wrap: wrap;
      color: #666;
      div {
        margin-bottom: 10px;
        > img {
          display: inline-block;
          width: 50px;
          height: 50px;
          .sku-state-mixin ();
        }
        > span {
          display: inline-block;
          height: 30px;
          line-height: 28px;
          padding: 0 20px;
          .sku-state-mixin ();
        }
      }
    }
  }
}
</style>
